#include <iostream>
#include <cstdio>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string>
#include <stdlib.h>
#include <arpa/inet.h>

using std::cout;
using std::cerr;
using std::endl;

#define IP  "0.0.0.0"
#define PORT 8081
#define MAX_SIZE 128

class UDP
{
    public:
        UDP():fd_(-1),ip_(IP),port_(PORT)
        {};

        ~UDP()
        {
            if(fd_ >= 0 )
            {
                close(fd_);
            }
        }

        bool Init()
        {
            fd_=socket(AF_INET,SOCK_DGRAM,0);
            if(fd_ < 0)
            {
                perror("socket created failed\n");
                return false;
            }
            cout<<"Init Socket Successed\n"<<"fd_:"<<fd_<<endl;
            return true;
        } 

        bool Bind()
        {
            struct sockaddr_in my_in;
            memset(&my_in,0,sizeof(my_in));
            my_in.sin_family=AF_INET;
            my_in.sin_port=htons(port_);
            my_in.sin_addr.s_addr=INADDR_ANY;
            int check=bind(fd_,(struct sockaddr*)&my_in,sizeof(my_in));
            if(check <0)
            {
                perror("socket bind failed\n");
                return false;
            }
            cout<<"Bind Socket Successed\n"<<endl;
            return true;
        }

        void Start()
        {
            char bar[MAX_SIZE];
            while(1)
            {
                struct sockaddr_in peer;
                socklen_t len=sizeof(peer);
                size_t size=recvfrom(fd_,bar,sizeof(bar)-1,0,(struct sockaddr*)&peer,&len);
                if(size >0)
                {
                    bar[MAX_SIZE-1]='\0';
                    int port=ntohs(peer.sin_port);
                    std::string ip=inet_ntoa(peer.sin_addr);
                    cout<<ip<<" : "<<port<<" say:"<<bar<<endl;
                }
                else
                {
                    perror("Recvfrom failed\n");
                }
            
                std::string echo_msg="";
                echo_msg+=bar;
                if(sendto(fd_,echo_msg.c_str(),sizeof(echo_msg),0,(struct sockaddr*)&peer,len))
                {
                    cout<<"Sendto successed"<<endl;
                }
                else
                {
                    cout<<"Sendto failed"<<endl;

                }
            }
        }

    private:
    int fd_;
    int port_;
    std::string ip_;
};